# coding=utf8
# 生成exe文件：
# pyinstaller -F upload.py
import urllib

import paramiko
import os
import re
import sys
import json
import time
import uuid
import threading
from stat import S_ISDIR
from hashlib import md5

#全局输出信息
global_print_msglist=[]
# 全局文件MD5
# {
#   "md5":file_path
# }
global_file_md5_map={}

# 全局工作目录
global_workDir = ""
#上传目录地址
global_uploadDir = ""
# 全局配置
global_configJson = {}
#配置文件地址
global_configFilePath = ""
# 日志文件地址
global_logFilePath = ""
# md5文件地址
global_md5FilePath = ""

def filter_path(path):
    path=re.sub('/+','/',path.replace('\\','/')).replace(':/', '://').strip()
    return path

    """
    param:`.SFTPAttributes`
    """
def check_isdir(fileAttr):
    return S_ISDIR(fileAttr.st_mode)
    
'''
删除地址左右分隔符
'''
def trim_slash(path):
    #去掉左边/
    index=path.find('/')
    if index==0:
        path=path[1:]
    #去掉右边/
    rindex=path.rfind('/')
    if rindex==len(path)-1:
        path=path[0:rindex]
    return path
#获取文件名称
def get_filename(path):
    path=filter_path(path)
    rindex=path.rfind('/')
    return path[rindex+1:]
#获取文件后缀
def get_fileext(path):
    path=filter_path(path)
    rindex=path.rfind('.')
    return path[rindex+1:].lower()

def loadJsonFile(jsonPath):
    jsonObj = None
    jsonPath = filter_path(jsonPath)
    if os.path.isfile(jsonPath):
        jsonFile = None
        try:
            jsonFile = open(jsonPath,mode='r')
            jsonObj = json.load(jsonFile)
        except Exception  as e:
            print str(e)
        finally:
            if jsonFile != None:
                jsonFile.close()
    return jsonObj

def saveJsonFile(jsonPath,jsonData):
    saveFlag = False
    jsonPath = filter_path(jsonPath)
    if jsonData != None:
        jsonFile = None
        try:
            jsonFile = open(jsonPath,mode='w')
            jsonFile.write(json.dumps(jsonData, ensure_ascii=False,sort_keys=False, indent=4, separators=(',', ': ')).encode('utf8'))
            jsonFile.flush()
            saveFlag = True
        except Exception  as e:
            print str(e)
        finally:
            if jsonFile != None:
                jsonFile.close()
    return saveFlag

def loadMd5File(md5FilePath):
    #读取md5配置
    try:
        global global_file_md5_map
        if len(md5FilePath)>0:
            tempMd5FileMap = loadJsonFile(md5FilePath)
        else:
            tempMd5FileMap = loadJsonFile(global_md5FilePath)
        if isinstance(tempMd5FileMap, (dict)):
            global_file_md5_map = tempMd5FileMap
            if len(md5FilePath)>0:
                saveJsonFile(global_md5FilePath, global_file_md5_map)
                #删除临时文件
                os.remove(md5FilePath)
                
    except Exception as e:
        print str(e)

#获取mac地址
def get_mac():
    node = uuid.getnode()
    mac = uuid.UUID(int = node).hex[-12:].upper()
    return mac

def print_2_encode(print_value):
    try:
        print print_value.encode('gbk')
        global global_print_msg
        global_print_msglist.append(time.strftime("%Y-%m-%d %H:%M:%S")+'    '+print_value)
        if len(global_logFilePath)>0:
            saveJsonFile(global_logFilePath, global_print_msglist)
    except Exception as e:
        print str(e)
#输出分割线
def print_line():
    print '-'*70
    global global_print_msg
    global_print_msglist.append(time.strftime("%Y-%m-%d %H:%M:%S")+'    '+'-'*70)
    if len(global_logFilePath)>0:
            saveJsonFile(global_logFilePath, global_print_msglist)


class MD5Util(object):
    def __init__(self,filePath):
        self.filePath = filePath
        self.md5Str = ""
        #相对路径
        global global_workDir
        self.relativePath = filter_path(filePath).replace(global_workDir,"")
        if os.path.isfile(self.filePath):
            md5File = None
            try:
                md5File = open(self.filePath,mode='r')
                self.md5Str = self.toMD5(md5File.read())
            except Exception as e:
                print str(e)
            finally:
                if md5File != None:
                    md5File.close()
#         print_2_encode(u'[File MD5] %s:%s' % (self.relativePath,self.md5Str))
    @classmethod
    def toMD5(self,data):
        m = md5();
        m.update(data);
        return m.hexdigest()
    
    def hasFileMd5(self):
#         global global_file_md5_map
        hasFileMd5 = False
        try:
            hasFileMd5 = global_file_md5_map[self.relativePath] == self.md5Str
#             print_2_encode(u'[Has File MD5,%s] %s:%s' % (hasFileMd5,self.relativePath,self.md5Str))
        except Exception as e:
            print str(e)
        return hasFileMd5
    def saveFileMd5(self):
        global global_file_md5_map
        global_file_md5_map[self.relativePath] = self.md5Str;
        #更新md5文件
        saveJsonFile(global_md5FilePath, global_file_md5_map)

#AES 加密
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
 
class AESUtil(object):
    def __init__(self, key):
        length = 16
        count = len(key)
        add = length - (count % length)
        self.key = key + ('\0' * add)
       
        self.mode = AES.MODE_CBC
     
    #加密函数，如果text不是16的倍数【加密文本text必须为16的倍数！】，那就补足为16的倍数
    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.key)
        #这里密钥key 长度必须为16（AES-128）、24（AES-192）、或32（AES-256）Bytes 长度.目前AES-128足够用
        length = 16
        count = len(text)
        add = length - (count % length)
        text = text + ('\0' * add)
        self.ciphertext = cryptor.encrypt(text)
        #因为AES加密时候得到的字符串不一定是ascii字符集的，输出到终端或者保存时候可能存在问题
        #所以这里统一把加密后的字符串转化为16进制字符串
        return b2a_hex(self.ciphertext)
     
    #解密后，去掉补足的空格用strip() 去掉
    def decrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.key)
        plain_text = cryptor.decrypt(a2b_hex(text))
        return plain_text.rstrip('\0')

#上传进度类
class ProgressThread (threading.Thread):
    def __init__(self,delay):
        threading.Thread.__init__(self)
        self.delay=delay    #进度条更新时间
        self.runFlag=True
        self.isResume=False
        self.progressNum=-1
    def run(self):
        while True:
            if self.runFlag:
                if self.isResume:
                    self.progressNum+=1
                    
                    p_str='/'
                    if self.progressNum%3==0:
                        p_str='/'
                    elif self.progressNum%3==1:
                        p_str='|'
                    else:
                        p_str='\\'
                        self.progressNum=-1
                    
                    progressShow='Upload progress: '
                    progressStrs=[]
                        
                    i=0
                    while i<10:
                        progressShow+='-%s'
                        progressStrs.append(p_str)
                        i+=1
                        
                    progressShow+='-\r'
                    sys.stdout.write(progressShow % tuple(progressStrs))
                    sys.stdout.flush()
                
                time.sleep(self.delay)
            else:
                pass
    
    def begin(self):
        self.runFlag=True
    def end(self):
        self.runFlag=False
    def suspend(self):
        self.isResume=False
    def resume(self):
        self.isResume=True

progressThread=ProgressThread(0.5)
progressThread.start()

class SSH(object):
    def __init__(self, host, port, username, password):
        self._host = host
        self._port = port
        self._username = username
        self._password = password
        self._transport = None
        self._sftp = None
        self._client = None
        self._connect()         #建立连接
        self.dirCount=0         #上传目录数量
        self.fileCount=0        #上传文件数量
        self.uploadSize=0       #上传大小
        self.downloadSize=0     #下载大小

    def _connect(self):
        transport = paramiko.Transport((self._host, self._port))
        transport.connect(username=self._username, password=self._password)
        self._transport = transport
        print_2_encode(u'【链接成功】connection successful')
    
    #执行命令
    def exec_command(self, command):
        if self._client is None:
            self._client = paramiko.SSHClient()
            self._client._transport = self._transport
            
        stdout, stderr = self._client.exec_command(command)
        
        outdata = stdout.read()
        errdata = stderr.read()
        
        return outdata,errdata
    
    def sftp(self):
        if self._sftp is None:
            self._sftp = paramiko.SFTPClient.from_transport(self._transport)
        return self._sftp;
    #下载
    def download(self, remotepath, localpath):
        self.sftp().get(remotepath, localpath)

    #上传
    def put(self, localpath, remotepath):
        self.sftp().put(localpath, remotepath)
    

    def close(self):
        if self._transport:
            self._transport.close()
        if self._client:
            self._client.close()
        if self._sftp:
            self._sftp.close()
    
    def isDir(self,remotePath):
        return check_isdir(self.sftp().stat(remotePath))
#end ssh

# 处理上传
    def upload(self, sourcePath, uploadDir,noUploadFileList,lastUploadTime,replaceAllFlg=False):
        ### 操作数据
        # 来源目录
        sourcePath = filter_path(sourcePath)
        
        # 目标路径
        uploadDir = filter_path(uploadDir)
        ### 验证数据
        if not os.path.exists(sourcePath):
            print_2_encode(u'[error]The upload resource does not exist:%s' % (sourcePath))
            return

        #进入上传目录
        try:
            if self.isDir(uploadDir):
                self.sftp().chdir(uploadDir)
                #远程文件目录
                remotefilelist=self.sftp().listdir()
                
                if os.path.isfile(sourcePath):
                    self.__uploadFile(sourcePath, uploadDir, remotefilelist,noUploadFileList,lastUploadTime,replaceAllFlg)
                elif os.path.isdir(sourcePath):
                    #上传目录
                    for filename in os.listdir(sourcePath):
                        sonFilePath=filter_path(os.path.join(sourcePath, filename))
                        if os.path.isdir(sonFilePath):
                            canUpload=True
                            if filename in remotefilelist:
                                    if replaceAllFlg==False:
                                        print_2_encode(u'[*] Directory already exists:%s' % (sonFilePath))
                                        print_2_encode(u'Confirm overwrite directory (y|n):')
                                        isReplace=raw_input(unicode('确认覆盖目录(y|n):','utf-8').encode('gbk'))
                                        if isReplace.lower() != 'y':
                                            canUpload=False
                            else:
                                try:
                                    #创建远程目录
                                    self.sftp().mkdir(filename)
                                    print_2_encode(u'[+] %s' % (sonFilePath))
                                    self.dirCount+=1
                                except Exception as e:
                                    canUpload=False
                                    print_2_encode(u'[-] Directory creation failed:%s->%s' % (sonFilePath,str(e)))
                            if canUpload:
                                try:
                                    self.upload(sonFilePath, uploadDir+'/'+filename,noUploadFileList,lastUploadTime,replaceAllFlg)
                                    #返回当前目录
                                    self.sftp().chdir('..')
                                except Exception as e:
                                    print_2_encode(u'[error]:' + str(e))
                                    print_2_encode(u'[error]:%s' % (str(e)))
                        else:
                            self.__uploadFile(sonFilePath, uploadDir, remotefilelist,noUploadFileList,lastUploadTime,replaceAllFlg)
            else:
                print_2_encode(u'uploadDir is not dir!!!')
        except Exception as e:
            print_2_encode(u'[error] upload fail:%s' % (uploadDir))
            raise e
            return
    # 传送文件
    def __uploadFile(self, sourcePath, uploadDir, remotefilelist,noUploadFileList,lastUploadTime,replaceAllFlg=False):
        if sourcePath not in noUploadFileList :
            if self.__canUpload(sourcePath):
                #检查json文件格式
                if sourcePath.lower().endswith('.json'):
                    try:
                        #加载json文件
                        json.load(open(sourcePath,mode='r'))
                    except Exception as e:
                        raise Exception(u'[error] load json file fail:%s->%s' % (sourcePath,str(e)))
                        return
                #上传文件
                filename=get_filename(sourcePath)
                remotePath=filter_path(uploadDir + '/' + filename)
                canUpload=True
                if lastUploadTime>0:
                    #文件修改时间>最后上传时间
                    filemtime=os.path.getmtime(sourcePath)
                    #文件创建时间>最后上传时间
                    filectime=os.path.getctime(sourcePath)
                    if filemtime<lastUploadTime and filectime<lastUploadTime:
                        canUpload=False
                if canUpload==True and filename in remotefilelist:
                        if replaceAllFlg==False:
                            print_2_encode(u'[*] file already exists:%s' % (sourcePath))
                            print_2_encode(u'Confirm the overwrite file (y|n):')
                            isReplace=raw_input(unicode('确认覆盖文件(y|n):','utf-8').encode('gbk'))
                            if isReplace.lower() != 'y':
                                canUpload=False
                if canUpload:
                    # 上传文件
                    try:
                        fileMd5Util = MD5Util(sourcePath)
                        hasFileMd5 = fileMd5Util.hasFileMd5()
                        if hasFileMd5:
                            print_2_encode(u'[-] file no edit:%s' % (fileMd5Util.relativePath))
                        else:
                            currentUploadFileSize = os.path.getsize(sourcePath);
                            #开启进度条
                            progressThread.resume()
                            self._sftp.put(sourcePath, remotePath)
                            print_2_encode(u'[+] size:[%d] %s' % (currentUploadFileSize,sourcePath))
                            self.fileCount+=1
                            self.uploadSize+=currentUploadFileSize
                            fileMd5Util.saveFileMd5()
                    except Exception as e:
                        print_2_encode(u'[-] upload fail:%s->%s' % (sourcePath,str(e)))
                    finally:
                        #结束进度条
                        progressThread.suspend()
            else:
                print_2_encode(u'[-] do not upload:%s' % (sourcePath))
    def __canUpload(self,sourcePath):
        fileext=get_fileext(sourcePath)
        canUpload = fileext not in ['exe','sh','py','pyc','spec','bat']
        canUpload = canUpload and sourcePath.lower().endswith('.py.config')==False and sourcePath.lower().endswith('.exe.config')==False
        canUpload = canUpload and sourcePath.lower().endswith('.py.log')==False and sourcePath.lower().endswith('.exe.log')==False
        if canUpload and global_configJson.has_key("uploadConfig") and global_configJson["uploadConfig"].has_key("regexList"):
            canUpload = False
            for regStr in global_configJson["uploadConfig"]["regexList"]:
                matchResult = re.match(regStr, sourcePath, re.I)
                if matchResult != None:
                    canUpload = True
                    break
        return canUpload
    
    """
                 加载远程文件列表
    """
    def remoteFileList(self,serverDir,sonPath,currLevel,maxLevel,fileList):
        if currLevel<=maxLevel:
            filePath=filter_path(serverDir+"/"+sonPath)
            if self.isDir(filePath):
                #远程文件目录
                remoteFileAttr=ssh.sftp().listdir_attr(filePath)
                for fileAttr in remoteFileAttr:
                    relativePath=filter_path(sonPath+"/"+fileAttr.filename)
                    print relativePath
                    fileList.append(relativePath)
                    #判断是否为目录
                    if check_isdir(fileAttr):
                        self.remoteFileList(serverDir, relativePath, currLevel+1, maxLevel, fileList)
            else:
                print sonPath
                fileList.append(sonPath)
    
    def downloadRemoteMd5File(self):
        try:
            progressThread.resume()
            md5FileName = get_filename(global_md5FilePath);
            remoteMd5Path = filter_path(global_uploadDir+"/"+md5FileName)
            tempMd5Path = filter_path(global_workDir+"/temp-"+md5FileName)
            self.download(remoteMd5Path, tempMd5Path)
            print_2_encode(u'[+] download %s ==> %s' % (md5FileName,global_md5FilePath))
            #重新加载md5文件
            loadMd5File(tempMd5Path)
        except Exception as e:
            os.remove(tempMd5Path)
            print_2_encode(u'[-] download md5 file fail:%s->%s' % (md5FileName,str(e)))
        finally:
            progressThread.suspend()
    def uploadMd5File(self):
        try:
            progressThread.resume()
            md5FileName = get_filename(global_md5FilePath);
            remoteMd5Path = filter_path(global_uploadDir+"/"+md5FileName)
            self.put(global_md5FilePath, remoteMd5Path)
            print_2_encode(u'[+] upload md5 %s ==> %s' % (global_md5FilePath,md5FileName))
        except Exception as e:
            print_2_encode(u'[-] upload md5 file fail:%s->%s' % (md5FileName,str(e)))
        finally:
            progressThread.suspend()
    def downloadRemoteFiles(self,serverDir,sonPath,currLevel,maxLevel,targetDir):
        if currLevel<=maxLevel:
            filePath=filter_path(serverDir+"/"+sonPath)
            if self.isDir(filePath):
                #远程文件目录
                remoteFileAttr=ssh.sftp().listdir_attr(filePath)
                for fileAttr in remoteFileAttr:
                    relativePath=filter_path(sonPath+"/"+fileAttr.filename)
                    #判断是否为目录
                    if check_isdir(fileAttr):
                        self.downloadRemoteFiles(serverDir, relativePath, currLevel+1, maxLevel,targetDir)
                    else:
                        self.downloadRemoteFiles(serverDir, relativePath, currLevel, maxLevel,targetDir)
            else:
                try:
                    canDownload = True
                    targetPath=filter_path(targetDir+"/"+sonPath)
                    targetFileDir=os.path.dirname(targetPath)
                    if global_configJson.has_key("downloadConfig") and global_configJson["downloadConfig"].has_key("regexList"):
                        canDownload = False
                        for regStr in global_configJson["downloadConfig"]["regexList"]:
                            matchResult = re.match(regStr, targetPath, re.I)
                            if matchResult != None:
                                canDownload = True
                                break
                    if canDownload:
                        #检查本地文件是否存在
                        fileMd5 = MD5Util(targetPath)
                        if fileMd5.hasFileMd5():
                            canDownload = False
                            print_2_encode(u'[-] download has file[%s] ==> %s' % (fileMd5.md5Str,targetPath))
                    
                    if canDownload:
                        progressThread.resume()
                        if not os.path.isdir(targetFileDir):
                            os.makedirs(targetFileDir)
                        self.download(filePath, targetPath)
                        print_2_encode(u'[+] download %s ==> %s' % (sonPath,targetPath))
                        self.fileCount+=1
                        self.downloadSize+=os.path.getsize(targetPath)
                        MD5Util(targetPath).saveFileMd5()
                except Exception as e:
                    print_2_encode(u'[-] download fail:%s->%s' % (sonPath,str(e)))
                finally:
                    progressThread.suspend()
#最后更新时间模式
lastUploadTimePattern="%Y-%m-%d %H:%M:%S"

#更新配置文件
def updateConfig(configFilePath,user,serverKey,configUrl,checkUploadTime,lastUploadTime,data):
    try:
        if global_configJson == None:
            configJson={}
        else:
            configJson = global_configJson
            
        configJson["user"]=user
        configJson["server"]=serverKey
        configJson["configUrl"]=configUrl
        configJson["checkUploadTime"]=checkUploadTime
        if lastUploadTime>0:
            timeStr=time.strftime(lastUploadTimePattern, time.localtime(lastUploadTime))
            configJson["lastUploadTime"]=timeStr
        if data is not None:
            configJson["data"]=data
        else:
            configJson["data"]={}
        
#         global global_file_md5_map
#         configJson["data"]["md5"]=global_file_md5_map
#         global global_print_msglist
#         configJson["data"]["msg"]=global_print_msglist
        
        saveJsonFile(configFilePath, configJson)
    except Exception as e:
        print_2_encode(u'write config error!!!-->%s' % (str(e)))
    

'''
{
    "lastUploadTime": "2020-12-13 18:20:08",
    "defaultOption": {默认操作
        "menuId": 2,
        "overwriteAll": "y",
        "confimUpload": "y"
    },
    "configUrl": "https://activity.cang2.com/ssh-upload",
    "checkUploadTime": false,
    "user": "zhangjindong",
    "server": "fish3_ac",
    "downloadConfig":{
        "regexList":[
            ".+(js|html)$"
        ]
    },
    "uploadConfig":{
        "regexList":[
            ".+(js|html)$"
        ]
    }
}
'''

if __name__ == "__main__":
    try:
        __port=22
        __mac=get_mac();
        
        print_2_encode(u'[本机MAC地址]:%s' % __mac)
        
        __server={}
        
        #配置文件地址
        __configUrl="https://activity.cang2.com/ssh-upload"
        #当前用户名
        __user=""
        #服务器
        __serverKey=""
        
        #最后更新时间
        lastUploadTime=0
        
        #检查最后更新时间
        checkUploadTime=False
        
        #不可上传文件列表
        noUploadFileList=[]
        
        currentExeFilePath=''
        exeFileConfigExt='.config'
        
        if len(sys.argv)>0:
            #TODO 获取当前工作目录
            workDir = os.getcwdu()
            global_workDir = filter_path(workDir+"/")
#             print_2_encode(u'[workDir]:%s' % workDir)
            
            #TODO 获取当前可执行文件路径
            currentExeFilePath=filter_path(unicode(sys.argv[0],'gbk'))
            noUploadFileList.append(currentExeFilePath)
#             print_2_encode(u'[currentExeFilePath]:%s' % currentExeFilePath)
            
            #执行文件名称
            currentExeFileName=os.path.basename(currentExeFilePath)
#             print_2_encode(u'[currentExeFileName]:%s' % currentExeFileName)
            
            #配置文件地址
            configFilePath=os.path.join(workDir,currentExeFileName+exeFileConfigExt)
            noUploadFileList.append(configFilePath)
            
            global_configFilePath = configFilePath
            global_logFilePath = os.path.join(workDir,currentExeFileName+'.log')
            global_md5FilePath = os.path.join(workDir,currentExeFileName+'.md5')
            print_2_encode(u'config path:%s' % configFilePath)
            print_2_encode(u'log path:%s' % global_logFilePath)
            print_2_encode(u'md5 path:%s' % global_md5FilePath)
            
            #读取日志配置
            try:
                global_print_msglist = loadJsonFile(global_logFilePath)
                if isinstance(global_print_msglist, (list)) == False:
                    global_print_msglist = []
            except Exception as e:
                print str(e)
            
            #加载默认MD5文件
            loadMd5File("")
            
            '''
                                    默认配置设置：
                                    默认执行菜单2操作
            "defaultOption": {
                "menuId": 2,
                "overwriteAll": "y",
                "confimUpload": "y"
            },
            '''
            
            try:
                configJson=loadJsonFile(configFilePath)
                if configJson != None:
                    global_configJson = configJson
                    if configJson.has_key('configUrl'):
                        __configUrl=configJson["configUrl"]
                        print_2_encode(u'【服务器地址】server path:%s' % __configUrl)
                        
                    if configJson.has_key('user'):
                        __user=configJson["user"]
                        print_2_encode(u'【上传账号】user:%s' % __user)
                        
                    if configJson.has_key('server'):
                        __serverKey=configJson["server"]
                        print_2_encode(u'【上传服务器】server:%s' % __serverKey)
                    
                    #读取加密密钥，如果设置密钥则使用密钥解码,若为设置，则使用mac解码
                    if configJson.has_key('secret'):
                        __mac=configJson["secret"]
                        print_2_encode(u'【加密密钥】secret:%s' % __mac)
                    else:
                        global_configJson["secret"] = __mac
                        
                    #判断是否检查最后上传时间
                    if configJson.has_key("checkUploadTime"):
                        checkUploadTime=configJson["checkUploadTime"]
                        print_2_encode(u'【检查最后上传时间】check last upload time:%s' % checkUploadTime)
                        
                    if checkUploadTime==True and configJson.has_key('lastUploadTime'):
                        lastUploadTime=time.mktime(time.strptime(configJson['lastUploadTime'], lastUploadTimePattern))
                        if lastUploadTime>time.time():
                            lastUploadTime=0
                        print_2_encode(u'【最后上传时间】last upload time:%s' % configJson['lastUploadTime'])
                else:
                    print_2_encode(u'【配置文件读取失败!!!】read config error!!!-->%s' % (str(e)))
            except Exception as e:
                print_2_encode(u'【配置文件读取失败!!!】read config error!!!-->%s' % (str(e)))
                
                
            if len(__user)>0 and len(__serverKey)>0:
                urlPath=__configUrl;
                if __configUrl.find("?")>0:
                    urlPath+="&"
                else:
                    urlPath+="?"
                urlPath+="user="+__user+"&server="+__serverKey
                urlPath=filter_path(urlPath)
#                 print_2_encode(u'url:%s' % urlPath)
                
                __requestIp=""
                try:
                    responseResult=urllib.urlopen(urlPath)
                    responseJson=json.load(responseResult);
                    
                    if responseJson.has_key("success") and responseJson["success"]==True:
                        aesUtil=AESUtil(__mac)
                        __server=json.loads(aesUtil.decrypt(responseJson["data"]["server"]))
                    else:
                        print_2_encode(u'Error[%d]:%s' % (responseJson["code"],responseJson["msg"]))
                    __requestIp=responseJson["data"]["requestIp"]
                    print_2_encode(u'【本机IP】local ip:%s' % __requestIp)
                except Exception as e:
                    print_2_encode(u'【配置文件加载失败】config file load error>%s' % (str(e)))
                
                if len(__requestIp)>0 and __server.has_key("ip") and __server.has_key("user") and __server.has_key("pwd") and __server.has_key("dir"):
                    __server["dir"]=filter_path(__server["dir"])
                    
                    # 要上传当前文件夹路径
                    sourcePath = filter_path(workDir)
                    print_2_encode(u'【资源目录】source dir:%s' % (sourcePath))
                    
                    #print_2_encode(u'服务器目录:'+uploadDir)
                    
                    ssh=None
                    try:
                        #链接服务器
                        ssh = SSH(__server["ip"], __port, __server["user"], __server["pwd"])
                        # 来源目录
                        sourcePath = filter_path(sourcePath)
                        
                        # 目标路径
                        uploadDir = serverDir = filter_path(__server["dir"])
                        global_uploadDir = uploadDir
                        #判断是否继续
                        goOn=True
                        
                        #文件列表
                        fileList=[]
                        
                        while goOn:
                            print_line()
                            print_2_encode(u'【菜单列表】Menu List:')
                            print_2_encode(u'【0】.【退出】Exit')
                            print_2_encode(u'【1】.【显示文件列表】Show File List')
                            print_2_encode(u'【2】.【上传文件】Upload File')
                            print_2_encode(u'【3】.【下载文件】Download File')
                            
                            #判断是否存在默认操作
                            hasDefaultOption = configJson.has_key("defaultOption")
                            if hasDefaultOption == True:
                                goOn = False
                                defaultOption = configJson["defaultOption"]
                                optNum = str(defaultOption["menuId"])
                            else:
                                optNum=raw_input(unicode('Please enter menu number:','utf-8').encode('gbk'))
                            
                            print_2_encode(u'【菜单编号】Menu Number：%s' %(optNum))
                            if optNum == '0':
                                #退出
                                goOn=False
                                #updateConfig(configFilePath, __user, __serverKey, __configUrl, checkUploadTime, lastUploadTime,None)
                            elif optNum == '1':
                                #显示文件列表
                                print_2_encode(u'Please enter the folder address to view (default current directory)')
                                sonDirName=raw_input(unicode('请输入需要查看的文件夹地址(默认当前目录):','utf-8').encode('gbk'))
                                try:
                                    print_2_encode(u'Please enter folder depth (default 0)')
                                    sonDirLevel=raw_input(unicode('请输入文件夹深度(默认0):','utf-8').encode('gbk'))
                                    if len(sonDirLevel)<=0:
                                        sonDirLevel=0
                                    else:
                                        sonDirLevel=int(sonDirLevel)
                                    print_2_encode(u'文件夹深度(Folder depth)：%s' %(sonDirLevel))
                                    ssh.remoteFileList(serverDir, sonDirName, 0, sonDirLevel, fileList)
                                    updateConfig(configFilePath, __user, __serverKey, __configUrl, checkUploadTime, lastUploadTime,{"fileList":fileList})
                                except Exception as e:
                                    print str(e)
                                    print_2_encode(u'【%s】 is not dir' % (sonDirName))
                            elif optNum == '2':
                                #文件上传
                                print_2_encode(u'Confirm upload (y|n)')
                                if hasDefaultOption == True and defaultOption.has_key("confimUpload"):
                                    confimUpload = defaultOption["confimUpload"]
                                else:
                                    confimUpload=raw_input(unicode('确认上传(y|n):','utf-8').encode('gbk'))
                                
                                print_line()
                                if confimUpload.lower() == 'y':
                                    try:
                                        print_line()
                                        progressThread.begin()
                                        print_2_encode(u'Whether to overwrite all files (y|n)')
                                        if hasDefaultOption == True and defaultOption.has_key("overwriteAll"):
                                            overwriteAll = defaultOption["overwriteAll"]
                                        else:
                                            overwriteAll=raw_input(unicode('是否覆盖所有文件(y|n):','utf-8').encode('gbk'))
                                        
                                        replaceAllFlg=False
                                        if overwriteAll.lower()=='y':
                                            replaceAllFlg=True
                                        
                                        #初始化上传参数
                                        ssh.dirCount=0
                                        ssh.fileCount=0
                                        ssh.uploadSize=0
                                        ssh.downloadRemoteMd5File()
                                        ssh.upload(sourcePath, uploadDir,noUploadFileList,lastUploadTime,replaceAllFlg);
                                        ssh.uploadMd5File()
                                        print_line()
                                        
                                        print_2_encode(u'Upload End!!!')
                                        print_2_encode(u'Upload Folder Count：%d' % (ssh.dirCount))
                                        print_2_encode(u'Upload File Count：%d' % (ssh.fileCount))
                                        print_2_encode(u'Upload File Size：%.2f M' % (float(ssh.uploadSize)/1024/1024))
                                        print_line()
                                        #更新配置
                                        updateConfig(configFilePath, __user, __serverKey, __configUrl, checkUploadTime, time.time(),None)
                                    except Exception as e:
                                        print str(e)
                                    finally:
                                        progressThread.end()
                            elif optNum == '3':
                                #文件下载
                                try:
                                    downloadConfig={}
                                    if configJson.has_key('downloadConfig'):
                                        downloadConfig=configJson['downloadConfig']
                                        
                                    print_line()
                                    progressThread.begin()
                                    #下载目录
                                    #print_2_encode(u'Please enter download directory (default current directory):');
                                    #downloadDir=raw_input(unicode('请输入下载目录(默认当前目录):','utf-8').encode('gbk'))
                                    #if len(downloadDir)<=0 or len(downloadDir.split())<=0:
                                    downloadDir=sourcePath
                                    
                                    print_2_encode(u'File download directory:');
                                    print_2_encode(u'文件下载目录：%s' %(downloadDir))
                                    
                                    #远程目录
                                    #print_2_encode(u'Please enter remote resource directory (default upload directory):');
                                    #remoteDir=raw_input(unicode('请输入远程资源目录(默认上传目录):','utf-8').encode('gbk'))
                                    #if len(remoteDir)<=0 or len(remoteDir.split())<=0:
                                    remoteDir=""
                                    #print_2_encode(u'远程资源目录：%s' %(remoteDir))
                                    
                                    downloadLevel=100
                                    if downloadConfig.has_key('showDownloadLevel') and downloadConfig['showDownloadLevel']==1:
                                        print_2_encode(u'Please enter download directory depth (default 0, upload directory):');
                                        downloadLevel=raw_input(unicode('请输入下载目录深度(默认0，上传目录):','utf-8').encode('gbk'))
                                        if len(downloadLevel)<=0:
                                            downloadLevel=0
                                        else:
                                            downloadLevel=int(downloadLevel)
                                        print_2_encode(u'File download directory depth:');
                                        print_2_encode(u'文件下载目录深度：%s' %(downloadLevel))
                                        
                                    
                                    #初始化下载参数
                                    ssh.fileCount=0
                                    ssh.downloadSize=0
                                    
                                    ssh.downloadRemoteMd5File()
                                    ssh.downloadRemoteFiles(serverDir, remoteDir, 0, downloadLevel, downloadDir)
                                    
                                    print_2_encode(u'Download End!!!')
                                    print_2_encode(u'Download File Count：%d' % (ssh.fileCount))
                                    print_2_encode(u'Download File Size：%.2f M' % (float(ssh.downloadSize)/1024/1024))
                                    print_line()
                                    updateConfig(configFilePath, __user, __serverKey, __configUrl, checkUploadTime, lastUploadTime,None)
                                except Exception as e:
                                    print str(e)
                                finally:
                                    progressThread.end()
                    except Exception as e:
                            print str(e)
                    finally:
                        if ssh is not None:
                            ssh.close()
                else:
                    print_2_encode(u'【没有权限】unauthorized!!!')
            else:
                print_2_encode(u'【配置无效，请联系管理员!!!】Invalid configuration, please contact administrator!!')
#                 updateConfig(configFilePath, __user, __serverKey, __configUrl, checkUploadTime, lastUploadTime,{"mac":__mac})
    except Exception as e:
        print str(e)
    finally:
        os.system("pause")